#include "axbopenglwidget.h"


float vertices[] = {
    0.5f, 0.5f, 0.0f,   // top right
    0.5f, -0.5f, 0.0f,  // bottom right
    -0.5f, 0.5f, 0.0f,  // top left
    -0.5f, -0.5f, 0.0f  // bottom left
};

// 新添加的索引数组, 每连续3个数代表1个三角形的3个顶点
unsigned int indices[] = {
    0, 1, 2, // first triangle
    1, 2, 3  // second triangle
};

GLuint VBO, VAO, EBO;

AXBOpenGLWidget::AXBOpenGLWidget(QWidget *parent)
    : QOpenGLWidget{parent}
    , m_shape(None)
{
}

AXBOpenGLWidget::~AXBOpenGLWidget()
{
    makeCurrent();
    glDeleteBuffers(1, &VBO);       // free VBO
    glDeleteVertexArrays(1, &VAO);  // free VAO
    glDeleteBuffers(1, &EBO);       // free EBO
    doneCurrent(); // exit current status (OpenGL)
}

void AXBOpenGLWidget::drawShape(Shape shape)
{
    m_shape = shape;
    update(); // 触发重新绘制
}

void AXBOpenGLWidget::setWireframe(bool wireframe)
{
    makeCurrent(); // invoke OpenGL API outside initializeGL/resizeGL/paintGL
    if (wireframe) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    } else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }
    update();
    doneCurrent();
}

void AXBOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    // 创建VBO, VAO objects, 赋予ID
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    // 绑定VBO, VAO objects
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    // 创建EBO, 绑定EBO objects
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 为当前绑定到target的缓冲区对象创建一个新的数据存储
    // 如果data 不是NULL, 则使用来自此指针的数据初始化存储
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 指定顶点属性index, size
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    // 开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);

#if 1
    glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind VBO
    glBindVertexArray(0);             // unbind VAO
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // unbind EBO
    // 解绑后(再次绑定前), 不能直接使用VBO, VAO, EBO
#endif

    bool success;
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shapes.vert");
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shapes.frag");
    success = shaderProgram.link();
    if (!success) { // error
        qDebug() << "ERR: " << shaderProgram.log();
    }
}

void AXBOpenGLWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void AXBOpenGLWidget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    shaderProgram.bind();
    glBindVertexArray(VAO);

    switch (m_shape) {
    case Rect:
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL /* &indices */);
        break;
    default:
        break;
    }
}
